package com.ffcs.crmd.tsp.server.netty;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ffcs.crmd.tsp.api.dto.netty.RemotingCommand;
import com.ffcs.crmd.tsp.api.netty.INettyChannelEventListener;
import com.ffcs.crmd.tsp.api.netty.INettyConfigServer;
import com.ffcs.crmd.tsp.api.netty.INettyInvokeCallback;
import com.ffcs.crmd.tsp.common.constant.LoggerName;
import com.ffcs.crmd.tsp.common.exception.TspRemotingException;
import com.ffcs.crmd.tsp.common.netty.NettyEvent;
import com.ffcs.crmd.tsp.core.netty.NettyEventExecuter;
import com.ffcs.crmd.tsp.core.netty.server.NettyRemotingServerAbstract;

import io.netty.channel.Channel;
import io.netty.util.ResourceLeakDetector;
import io.netty.util.ResourceLeakDetector.Level;

/**
 * 
 * 功能说明:netty通信服务端
 *
 * @author ZHONGFUHUA
 * 
 * @since 1.0.0-SNAPSHOT
 *
 */
public class NettyRemotingServer extends NettyRemotingServerAbstract {
    
    /**
     * 日志
     */
    private static final Logger LOG                           = LoggerFactory.getLogger(LoggerName.RemotingLoggerName);
    
    /**
     * 获取信号量超时时间
     */
    private static final int    semaphoreTimeoutMillisDefault = 3000;
    
    /**
     * 获取响应超时时间
     */
    private static final int    reponseTimeoutMillisDefault   = -1;
    
    /**
     * 获取响应超时时间
     */
    private static final int    syncTimeoutMillisDefault      = 10000;
    
    /**
     * netty事件处理线程
     */
    private NettyEventExecuter  clientNettyEventExecuter;
    
    /**
     * netty事件处理线程
     */
    private NettyEventExecuter  taskNettyEventExecuter;
    
    public NettyRemotingServer(INettyConfigServer nettyServerConfig, INettyChannelEventListener taskChannelEventListener,
        INettyChannelEventListener clientChannelEventListener) {
        super(nettyServerConfig);
        
        ResourceLeakDetector.setLevel(Level.ADVANCED);
        clientNettyEventExecuter = new NettyEventExecuter(clientChannelEventListener, "TspServerNettyClientEvent");
        taskNettyEventExecuter = new NettyEventExecuter(taskChannelEventListener, "TspServerNettyTaskEvent");
    }
    
    @Override
    public void start() throws TspRemotingException {
        super.start();
        clientNettyEventExecuter.start();
        taskNettyEventExecuter.start();
        LOG.info("SERVER-NETTY: server netty remoting start ok.");
    }
    
    @Override
    public void shutdown() {
        super.shutdown();
        clientNettyEventExecuter.shutdown();
        taskNettyEventExecuter.shutdown();
        LOG.info("SERVER-NETTY: server netty remoting shutdown ok.");
    }
    
    @Override
    public RemotingCommand invokeSync(Channel channel, RemotingCommand request) throws TspRemotingException {
        return invokeSync(channel, request, syncTimeoutMillisDefault);
    }
    
    @Override
    public RemotingCommand invokeSync(Channel channel, RemotingCommand request, long timeoutMillis) throws TspRemotingException {
        return super.invokeSyncImpl(channel, request, timeoutMillis);
    }
    
    @Override
    public void invokeAsync(Channel channel, RemotingCommand request, INettyInvokeCallback invokeCallback){
        invokeAsync(channel, request, invokeCallback, null);
    }
    
    @Override
    public void invokeAsync(Channel channel, RemotingCommand request, INettyInvokeCallback invokeCallback, INettyInvokeCallback sendFailInvokeCallback) {
        invokeAsync(channel, request, reponseTimeoutMillisDefault, invokeCallback, sendFailInvokeCallback);
    }
    
    @Override
    public void invokeAsync(Channel channel, RemotingCommand request, long reponseTimeoutMillis, INettyInvokeCallback invokeCallback){
        invokeAsync(channel, request, reponseTimeoutMillis, invokeCallback);
    }
    
    @Override
    public void invokeAsync(Channel channel, RemotingCommand request, long reponseTimeoutMillis, INettyInvokeCallback invokeCallback, INettyInvokeCallback sendFailInvokeCallback){
        super.invokeAsyncImpl(channel, request, semaphoreTimeoutMillisDefault, reponseTimeoutMillis, invokeCallback, sendFailInvokeCallback);
    }
    
    @Override
    public void invokeOneway(Channel channel, RemotingCommand request) {
        super.invokeOnewayImpl(channel, request, semaphoreTimeoutMillisDefault, null);
    }
    
    @Override
    public void putNettyEvent(NettyEvent event) {
        taskNettyEventExecuter.putNettyEvent(event);
        clientNettyEventExecuter.putNettyEvent(event);
    }
    
    @Override
    public Logger getLog() {
        return LOG;
    }
    
}
